//
//  策略模式通用代码.swift
//  StrategyPattern
//
//  Created by mac on 2017/11/9.
//  Copyright © 2017年 RRC. All rights reserved.
//

import Foundation

/**
 注：策略模式的重点就是封装角色，它是借用代理模式的思路，它和代理模式的差别就是策略模式的封装角色和被封装的策略类不用是同一个接口，如果是同一个接口那就成了代理模式了。
 */

//抽象策略角色------策略、算法家族的抽象，通常为接口，定义每个策略或算法必须具有的方法和属性。
protocol TYStrategy {
    //策略模式的运算法则
    func doSomething()
}

//封装角色-----也叫上下文角色，起承上启下封装作用，屏蔽高层模块对策略、算法的直接访问，封装可能存在的变化。
public class TYContext{
    //抽象策略
    private let strategy:TYStrategy
    //通过构造函数实现具体的策略
    init(strategy:TYStrategy) {
        self.strategy = strategy
    }
    //封装后的策略方法
    func doAnything(){
        self.strategy.doSomething()
    }
}

//具体策略角色------实现抽象策略中的操作，该类含有具体的算法
public class ConcreteStrategyA:TYStrategy{
    func doSomething() {
        print("具体策略1的运算法则")
    }

}

public class ConcreteStrategyB:TYStrategy{
    func doSomething() {
        print("具体策略2的运算法则")
    }
    
}

//高层模块／使用场景类
public class Client{
    public static func main(args:[String]){
        //声明一个具体的策略
        let strategyA:TYStrategy = ConcreteStrategyA()
        //声明上下文对象
        var context:TYContext = TYContext(strategy: strategyA)
        //执行封装后的方法
        context.doAnything()
        
        //再声明一个具体的策略
        let strategyB:TYStrategy = ConcreteStrategyB()
        context = TYContext(strategy: strategyB)
        context.doAnything()
        
    }
}

/**
 策略模式的优点：
    1､算法可以自由功换----这是策略模式本身定义的，只要实现抽象策略，它就成为策略家族的一个成员，通过封装角色对其进行封装，保证对外提供“可自由切换”的策略。
    2､避免使用多重条件判断
    3､扩展性良好
 缺点：
    1､策略类数量增多----每一个策略都是一个类，复用的可能性很小，类数量增多。
    2､所有的策略类都需要对外暴露
 */
